﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.ComponentModel;
using System.Reflection;

namespace Camadas
{
    public class GenericoDAO<T, TipoID> : PadraoDAO<T, TipoID>
    {
        string nomeArquivo;
        Stream arquivo;
        BinaryFormatter binario = new BinaryFormatter();
        List<T> lista;

        public GenericoDAO()
    {
        nomeArquivo = typeof(T).Name; //this.GetType().Name;
    }

        #region PadraoDAO<T,TipoID> Members

        public T SelID(TipoID id)
        {
            throw new NotImplementedException();
        }

        public T SelID(TipoID id, bool travar)
        {
            throw new NotImplementedException();
        }

        public IList<T> SelTodos()
        {
            try
            {
                if (File.Exists(@"C:\Dados\" + nomeArquivo + ".dat"))
                {
                    arquivo = new FileStream(@"C:\Dados\" + nomeArquivo + ".dat", FileMode.Open);
                    lista = (List<T>)binario.Deserialize(arquivo);
                    arquivo.Close();
                }

                if (lista == null || lista.Count == 0)
                    lista = new List<T>();

                return lista;
            }
            catch (Exception ex)
            {
                throw new System.Exception("erro ae:", ex);
            }
            finally
            {
                if (File.Exists(@"C:\Dados\" + nomeArquivo + ".dat"))
                {
                    arquivo.Dispose();
                }                
            }
        }

        public T Salvar(T entidade)
        {
            try
            {
                if (File.Exists(@"C:\Dados\" + nomeArquivo + ".dat"))
                {
                    arquivo = new FileStream(@"C:\Dados\" + nomeArquivo + ".dat", FileMode.Open);
                    lista = (List<T>)binario.Deserialize(arquivo);
                    arquivo.Close();
                }

                if (lista == null || lista.Count == 0)
                    lista = new List<T>();

                lista.Add(entidade);

                arquivo = new FileStream(@"C:\Dados\" + nomeArquivo + ".dat", FileMode.Create);
                binario.Serialize(arquivo, lista);
                arquivo.Close();

                return entidade;

            }
            catch (Exception ex)
            {
                throw new System.Exception("erro ae:", ex);
            }
            finally
            {
                arquivo.Dispose();
            }
        }

        public T Atualizar(T entidade)
        {
            try
            {
                if (File.Exists(@"C:\Dados\" + nomeArquivo + ".dat"))
                {
                    arquivo = new FileStream(@"C:\Dados\" + nomeArquivo + ".dat", FileMode.Open);
                    lista = (List<T>)binario.Deserialize(arquivo);
                    arquivo.Close();
                }

                if (lista == null || lista.Count == 0)
                    return entidade;

                T n = lista.Find(i => i.Equals(entidade));

                arquivo = new FileStream(@"C:\Dados\" + nomeArquivo + ".dat", FileMode.Create);
                binario.Serialize(arquivo, lista);
                arquivo.Close();

                return entidade;

            }
            catch (Exception ex)
            {
                throw new System.Exception("erro ae:", ex);
            }
            finally
            {
                arquivo.Dispose();
            }
        }

        public void Deletar(T entidade)
        {
            try
            {
                if (File.Exists(@"C:\Dados\" + nomeArquivo + ".dat"))
                {
                    arquivo = new FileStream(@"C:\Dados\" + nomeArquivo + ".dat", FileMode.Open);
                    lista = (List<T>)binario.Deserialize(arquivo);
                    arquivo.Close();
                }


                string campoChave = pegaCampoChave(entidade);
                T entidadeTO = (T)entidade;
                object valorChave = entidadeTO.GetType().GetProperty(campoChave).GetValue(entidadeTO, null);
                lista.RemoveAll(item => item.GetType().GetProperty(campoChave).GetValue(item, null).Equals(valorChave));

                //gene = lista.FindAll(delegate(T z) { return z.GetType().GetProperty(nome).GetValue(z, null) == emp.GetType().GetProperty(nome).GetValue(emp, null); } );

                arquivo = new FileStream(@"C:\Dados\" + nomeArquivo + ".dat", FileMode.Create);
                binario.Serialize(arquivo, lista);
                arquivo.Close();

            }
            catch (Exception ex)
            {
                throw new System.Exception("erro ae:", ex);
            }
            finally
            {
                arquivo.Dispose();
            }
        }

        private string pegaCampoChave(T entidade)
        {            
            foreach (PropertyInfo item in typeof(T).GetProperties())
            {
                object[] atributos = item.GetCustomAttributes(typeof(DataObjectFieldAttribute), false);
                foreach (object atributo in atributos)
                {
                    DataObjectFieldAttribute campoAtributo = (DataObjectFieldAttribute)atributo;
                    if (campoAtributo.PrimaryKey)
                    {
                        return item.Name;
                    }
                }
            }
            return string.Empty;
        }

        #endregion
    }
}
